package com.rc.evcharger.action;

import com.rc.evcharger.common.base.BaseCommAction;
import com.rc.evcharger.common.code.StdControlCode;
import com.rc.evcharger.common.constant.SocketConstant;
import com.rc.evcharger.common.constant.WebConstant;
import com.rc.evcharger.common.terminal.*;
import com.rc.evcharger.common.terminal.ElecPileFauthResult;
import com.rc.evcharger.common.terminal.UnLockResult;
import com.rc.evcharger.common.type.CardNoData;
import com.rc.evcharger.common.type.ChargeBalaceData;
import com.rc.evcharger.common.type.UserAccountData;
import com.rc.evcharger.common.type.VinCodeData;
import com.rc.evcharger.model.elec.ElecGun;
import com.rc.evcharger.model.elec.ElecPile;
import com.rc.evcharger.model.elec.ElecStation;
import com.rc.evcharger.model.member.MemberCard;
import com.rc.evcharger.model.member.MemberInfo;
import com.rc.evcharger.model.order.OrderInfo;
import com.rc.evcharger.service.elec.ElecGunService;
import com.rc.evcharger.service.elec.ElecPileHostService;
import com.rc.evcharger.service.elec.ElecPileService;
import com.rc.evcharger.service.elec.ElecStationService;
import com.rc.evcharger.service.member.MemberCardService;
import com.rc.evcharger.service.member.MemberInfoService;
import com.rc.evcharger.service.order.OrderInfoService;
import com.rc.evcharger.service.tenant.TenantSettingService;
import com.rc.evcharger.dto.msg.TerminalMessage;
import com.rc.evcharger.dto.terminal.CardNoResult;
import com.rc.evcharger.dto.terminal.ChargeBalaceResult;
import com.rc.evcharger.dto.terminal.UserAccountResult;
import com.rc.evcharger.dto.terminal.VinVehicleResult;
import com.rc.evcharger.dto.utils.MessageUtil;
import com.rc.evcharger.service.ChargeMessageService;
import com.rc.evcharger.task.ExOrderTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.List;

/**
 * 本地执行的逻辑（偏通讯）,会返回响应指令
 */
@Component
public class StdCommAction implements BaseCommAction<TerminalMessage> {
    private static Logger logger = LoggerFactory.getLogger(StdCommAction.class);

    @Autowired
    private ExOrderTask exOrderTask;

    @Autowired
    private ElecPileService elecPileService;

    @Autowired
    private MemberInfoService memberService;

    @Autowired
    private MemberCardService memberCardService;

    @Autowired
    private OrderInfoService orderInfoService;

    @Autowired
    private TenantSettingService tenantSettingService;

    @Autowired
    private ElecGunService elecGunService;

    @Autowired
    private ElecStationService elecStationService;

    @Autowired
    private ElecPileHostService elecPileHostService;

    @Autowired
    private ChargeMessageService chargeMessageService;

    /**
     * 登录指令
     *
     * @param msg
     * @return
     */
    @Override
    public String login(TerminalMessage msg) {
        ElecPile pile = elecPileService.selectPileByLogicAddress(msg.getRtua());
        if (pile == null) {
            return "";
        }
        exOrderTask.removeTask(pile.getPileRtua());

        //回复桩
        return MessageUtil.getResponse(msg, StdControlCode.RESP_LOGIN, false);
    }

    /**
     * 登出
     * 桩改变离线状态，添加桩的异常结算定时器（如果桩有枪在充电），添加改变用户充电 枪状态定时器，发送数据到羊城充
     *
     * @param msg
     * @return
     */
    @Override
    public String logout(TerminalMessage msg) {

        ElecPile pile = elecPileService.selectPileByLogicAddress(msg.getRtua());
        if (pile == null) {
            return "";
        }

        //TODO 可能需要事务
        chargeMessageService.loginOut(pile);

        if (pile.getElecStationId().longValue() == 85L) {
            exOrderTask.addTask(pile.getPileRtua(), null, 270, null);
        } else if (pile.getElecStationId().longValue() == 10609L &&
                (pile.getPileElecType().equals("1") || pile.getPileElecType().equals("4"))) {
            //羽毛球馆
            exOrderTask.addTask(pile.getPileRtua(), null, 300, null);
        }
        //派诺101  新亚232 260
        else if ("232".equals(pile.getProgramVersion()) || "101".equals(pile.getProgramVersion())) {
            //不会添加结算定时器
            logger.warn("离线不会添加结算定时器，桩编号:{},版本号", pile.getPileNo(), pile.getProgramVersion());
        } else if ("260".equals(pile.getProgramVersion()) || "102".equals(pile.getProgramVersion())) {
            //不会添加结算定时器
            logger.warn("离线不会添加结算定时器，桩编号:{}", pile.getPileNo(), pile.getProgramVersion());
        } else if ("311".equals(pile.getProgramVersion())) {
            //不会添加结算定时器
            logger.warn("hjl离线不会添加结算定时器，桩编号:{}", pile.getPileNo());
        }else if ("234".equals(pile.getProgramVersion())) {
            //不会添加结算定时器
            logger.warn("降功率离线不会添加结算定时器，桩编号:{}", pile.getPileNo());
        }
        else {
            exOrderTask.addTask(pile.getPileRtua(), null, null, null);
        }


        return MessageUtil.getResponse(msg, StdControlCode.RESP_LOGOUT, false);
    }

    /**
     * 心跳检查
     */
    @Override
    public String hearBeat(TerminalMessage msg) {
        ElecPile pile = elecPileService.selectPileByLogicAddress(msg.getRtua());
        //防止有心跳却离线
        int loginStatus = elecPileService.isLoginStatus(pile);
        if (loginStatus == SocketConstant.CON0) {
            return "";
        }

        //更新桩通讯地址
        elecPileHostService.updateHostByElecPileId(pile.getElecPileId());

        return MessageUtil.getResponse(msg, StdControlCode.RESP_HEARTBEAT_MONITOR, false);
    }


    /**
     * 充电数据自动上报 获取充电数据并存入redis中
     */
    @Override
    public String chargeReport(TerminalMessage msg) {
        return "";
    }

    /**
     * 收到A6指令做结算处理
     *
     * @param msg
     * @return
     */
    @Override
    public String chargeBalance(TerminalMessage msg) {
        ElecPile pile = elecPileService.selectPileByLogicAddress(msg.getRtua());

        Result result = new ChargeBalaceResult();
        ChargeBalaceResult cbr = result.getResult(msg.getData());


        cbr.setPileId(pile.getElecPileId());

        ChargeBalaceData chargeBalaceData = new ChargeBalaceData();
        chargeBalaceData.setOrderNum(cbr.getOrderNum());
        chargeBalaceData.setStatus("01");

        TerminalMessage message = new TerminalMessage(pile.getPileRtua(), StdControlCode.ELEC_DATA_BALANCE_RES, chargeBalaceData);
        return MessageUtil.getResponseData(message, StdControlCode.ELEC_DATA_BALANCE_RES, false);
    }

    /**
     * 读取控制充电的操作结果
     */
    @Override
    public String readElecControl(TerminalMessage msg) {
        return "";
    }

    /**
     * 读取车辆VIN，实现插枪充电
     */
    @Override
    public String readVinControl(TerminalMessage msg) {
        //获取桩
        ElecPile pile = elecPileService.selectPileByLogicAddress(msg.getRtua());

        //获取车辆VIN码的对象
        Result result = new VinVehicleResult();
        VinVehicleResult vinResult = result.getResult(msg.getData());

        VinCodeData vinCodeData = new VinCodeData();
        vinCodeData.setGunNum(WebConstant.CON0 + vinResult.getGunNum());

        TerminalMessage message = new TerminalMessage(pile.getPileRtua(), StdControlCode.CARD_NO_23_RESPONSE, vinCodeData);
        return MessageUtil.getResponseData(message, StdControlCode.VICHELE_VIN_REPORT_RESPONSE, false);
    }

    /**
     * 电桩告警报文解析
     */
    @Override
    public String elecPileFault(TerminalMessage msg) {
        //获取桩
        ElecPile pile = elecPileService.selectPileByLogicAddress(msg.getRtua());

        //解析告警记录
        FaultCodeResult result = new FaultCodeResult();
        List<FaultCodeResult> fcr = result.getResult(msg.getData());

        ElecPileFauthResult elecPileFauthResult = new ElecPileFauthResult();
        String gunNum = fcr.get(0).getGunNum();
        elecPileFauthResult.setGunNum(gunNum);

        TerminalMessage message = new TerminalMessage(pile.getPileRtua(), StdControlCode.RESP_EXCEPTON_WARN, elecPileFauthResult);
        return MessageUtil.getResponseData(message, StdControlCode.RESP_EXCEPTON_WARN, false);
    }


    /**
     * 读取解锁的操作结果
     */
    @Override
    public String readUnLock(TerminalMessage msg) {
        ElecPile pile = elecPileService.selectPileByLogicAddress(msg.getRtua());
        //解析告警记录
        UnLockResult result = new UnLockResult();

        UnLockResult unLockResult = result.getResult(msg.getData());

        if (unLockResult.getLockStatus().endsWith(SocketConstant.CON1 + "")) {
            logger.warn("电桩" + pile.getPileRtua() + "的" + unLockResult.getGunNum() + "号枪解锁成功");
        } else {
            logger.warn("电桩" + pile.getPileRtua() + "的" + unLockResult.getGunNum() + "号枪解锁失败");
        }
        return "";
    }

    @Override
    public String timing(TerminalMessage msg) {
        //校时暂不做处理
        return null;
    }


    /**
     * 读取卡号
     */
    @Override
    public String readCardNo(TerminalMessage msg) {
        ElecPile pile = elecPileService.selectPileByLogicAddress(msg.getRtua());
        //解析告警记录
        Result result = new CardNoResult();

        CardNoResult cardNoResult = result.getResult(msg.getData());

        MemberInfo memberInfo = memberService.selectCardNo(cardNoResult.getCardNo(), pile.getTenantCode());
        ElecGun elecGun = elecGunService.validGun(pile, cardNoResult.getGunNum());

        String status = "01";

        MemberCard memberCard = null;
        BigDecimal money = BigDecimal.ZERO;

        if (memberInfo == null) {
            //卡不存在
            CardNoData cardNoData = new CardNoData(cardNoResult.getGunNum(), "03", "00 00 00 00");
            TerminalMessage message = new TerminalMessage(pile.getPileRtua(), StdControlCode.CARD_NO_23_RESPONSE, cardNoData);
            return MessageUtil.getResponseData(message, StdControlCode.CARD_NO_23_RESPONSE, false);
        }

        if ("3".equals(memberInfo.getMemberType())) {
            //互联互通用户不进行刷卡启动
            CardNoData cardNoData = new CardNoData(cardNoResult.getGunNum(), "04", "00 00 00 00");
            TerminalMessage message = new TerminalMessage(pile.getPileRtua(), StdControlCode.CARD_NO_23_RESPONSE, cardNoData);
            return MessageUtil.getResponseData(message, StdControlCode.CARD_NO_23_RESPONSE, false);
        }

        if ("1".equals(memberInfo.getStatus())) {
            //会员被冻结
            CardNoData cardNoData = new CardNoData(cardNoResult.getGunNum(), "04", "00 00 00 00");
            TerminalMessage message = new TerminalMessage(pile.getPileRtua(), StdControlCode.CARD_NO_23_RESPONSE, cardNoData);
            return MessageUtil.getResponseData(message, StdControlCode.CARD_NO_23_RESPONSE, false);
        }


        money = memberInfo.getJoinMemberAccount().getAccount();


        memberCard = memberCardService.selectMemberId(memberInfo.getMemberId());
        if (!(SocketConstant.CON1 + "").equals(memberCard.getOperateStatus())) {
            //未绑定或已注销
            CardNoData cardNoData = new CardNoData(cardNoResult.getGunNum(), "04", "00 00 00 00");
            TerminalMessage message = new TerminalMessage(pile.getPileRtua(), StdControlCode.CARD_NO_23_RESPONSE, cardNoData);
            return MessageUtil.getResponseData(message, StdControlCode.CARD_NO_23_RESPONSE, false);
        }


        //停止
        if ("02".equals(cardNoResult.getStatus())) {
            OrderInfo orderInfo = orderInfoService.selectNewOrderByMemberIdAndGunId(memberInfo.getMemberId(), elecGun.getElecGunId());
            if (orderInfo != null && !"2".equals(orderInfo.getStatus())) {
                //StopChargeReq stopChargeReq = new StopChargeReq();
                //stopChargeReq.setElecPileId(pile.getElecPileId());
                //stopChargeReq.setOrderNum(orderInfo.getOrderNum());
                //stopChargeReq.setGunNum(cardNoResult.getGunNum());
                //stopChargeReq.setMemberId(memberInfo.getMemberId());
                //stopChargeReq.setStopType(SocketConstant.STOP_PAY_CARD_0XD);
                //String msg0 = JSON.toJSONString(stopChargeReq);
                //mqProducer.sendDelay(MqConfig.CONTROLL_CARDNO, msg0, 3000);
                CardNoData cardNoData = new CardNoData(cardNoResult.getGunNum(), "01", "00 00 00 00");
                cardNoData.parseAccount(money);
                TerminalMessage message = new TerminalMessage(pile.getPileRtua(), StdControlCode.CARD_NO_23_RESPONSE, cardNoData);
                return MessageUtil.getResponseData(message, StdControlCode.CARD_NO_23_RESPONSE, false);
            }
        }

        //启动前判断站、桩是否下线
        ElecStation elecStation = elecStationService.selectByPrimaryKey(pile.getElecStationId());
        String operateStatus = elecStation.getOperateStatus() + pile.getOperateStatus() + elecGun.getOperateStatus();
        if (!operateStatus.equals("111")) {

            CardNoData cardNoData = new CardNoData(cardNoResult.getGunNum(), "05", "00 00 00 00");
            cardNoData.parseAccount(money);
            TerminalMessage message = new TerminalMessage(pile.getPileRtua(), StdControlCode.CARD_NO_23_RESPONSE, cardNoData);
            return MessageUtil.getResponseData(message, StdControlCode.CARD_NO_23_RESPONSE, false);

        }


        //得到对应钱包
        //用户是否在充电 0不是，1正充电                         充电类型 0单冲 1多充 默认0
        if ("1".equals(memberInfo.getChargeStatus()) && "0".equals(memberInfo.getChargeType())) {
            logger.warn("该会员正在充电中，不能重复发起充电，会员手机号码：" + memberInfo.getMobile());
            CardNoData cardNoData = new CardNoData(cardNoResult.getGunNum(), "09", "00 00 00 00");
            TerminalMessage message = new TerminalMessage(pile.getPileRtua(), StdControlCode.CARD_NO_23_RESPONSE, cardNoData);
            return MessageUtil.getResponseData(message, StdControlCode.CARD_NO_23_RESPONSE, false);
        }

        // 1多充
        if (memberInfo.getChargeType().equals(SocketConstant.CON1 + "")) {

            Integer number = orderInfoService.countElecOrder(memberInfo) + 1;

            BigDecimal mult_charge_account_limit = tenantSettingService.query_mult_charge_account_limit(memberInfo.getTenantCode());
            BigDecimal startMoney = mult_charge_account_limit.multiply(new BigDecimal(number));

            //多充会员启动的余额大于  单次启动金额*（正在充电订单数+1）
            if (startMoney.compareTo(money) == 1) {
                logger.warn("该一号多充余额不足，会员手机号码：" + memberInfo.getMobile());
                CardNoData cardNoData = new CardNoData(cardNoResult.getGunNum(), "02", "00 00 00 00");
                cardNoData.parseAccount(money);
                TerminalMessage message = new TerminalMessage(pile.getPileRtua(), StdControlCode.CARD_NO_23_RESPONSE, cardNoData);
                return MessageUtil.getResponseData(message, StdControlCode.CARD_NO_23_RESPONSE, false);
            }
        }

        //单充用户最小启动充电余额
        BigDecimal start_charge_account_limit = tenantSettingService.query_start_charge_account_limit(memberInfo.getTenantCode());
        if (money == null || money.intValue() < start_charge_account_limit.intValue()) {
            logger.warn("该会员余额不足，会员手机号码：" + memberInfo.getMobile());
            CardNoData cardNoData = new CardNoData(cardNoResult.getGunNum(), "02", "00 00 00 00");
            cardNoData.parseAccount(money);
            TerminalMessage message = new TerminalMessage(pile.getPileRtua(), StdControlCode.CARD_NO_23_RESPONSE, cardNoData);
            return MessageUtil.getResponseData(message, StdControlCode.CARD_NO_23_RESPONSE, false);
        }

        //启动
        CardNoData cardNoData = new CardNoData();
        cardNoData.setStatus(status);
        cardNoData.setGunNum(cardNoResult.getGunNum());
        if (memberInfo != null) {
            cardNoData.parseAccount(memberInfo.getJoinMemberAccount().getAccount());
        } else {
            cardNoData.setAccount("00 00 00 00");
        }

        TerminalMessage message = new TerminalMessage(pile.getPileRtua(), StdControlCode.CARD_NO_23_RESPONSE, cardNoData);
        return MessageUtil.getResponseData(message, StdControlCode.CARD_NO_23_RESPONSE, false);
    }

    /**
     * 用户余额回复指令
     */
    @Override
    public String powerOff(TerminalMessage msg) {
        return "";
    }

    @Override
    public String userAccount(TerminalMessage msg) {
        ElecPile pile = elecPileService.selectPileByLogicAddress(msg.getRtua());
        //解析告警记录
        Result result = new UserAccountResult();

        UserAccountData userAccountData = result.getResult(msg.getData());
        logger.info("用户余额回复,对应桩编号:{},枪号:{},余额:{}", pile.getPileNo(), userAccountData.getGunNum(), userAccountData.getUserAccount());
        return "";
    }
}
